(*application
  addition
  soustraction
  +Multiplication
  +deriviée*)
power 5 2;;
application [(2,2);(2,3);(4,4)] 2;;
add [(1,2);(2,6);(7,8);(2,12)] [(1,4);(3,6);(1,9)];;
soustract [(1,2);(2,6);(7,8);(2,12)] [(1,4);(3,6);(1,9)];;
deriv [(2,2);(2,3);(4,4)];;
(*représentation d'un polynôme TOUJOURS EN ORDRE CROISSANT DES EXPOSANTS
polynôme vide = 0*)
let polynome = [(1,1);(5,2);(2,3);(7,6)];;

(*pour pouvoir appliquer une fonction polynomiale il faut pouvoir calculer des puissances*)
(*calcul x puissance n avec n >= 0 *)
let rec power x n = match n with
   0 -> 1
  |n when n > 0 ->
    if ((n mod 2) = 1) then
      x * (power (x * x) (n / 2))
    else
      power (x * x) (n / 2)
  |_ -> failwith "n < 0";;

(*calcul du polynome list en x*)
let rec application list x =
  match list with
      [] -> 0
  |(a,n)::l -> a * (power x n) + application l x;;

application [(2,2);(2,3);(4,4)] 2;;

(*ajoute le polynôme list1 et le polynôme list2*)
let rec add list1 list2 = match (list1,list2) with
    ([],l)|(l,[]) -> l
  |( (a,n)::l1 , (b,n2)::l2) when n < n2 -> (a,n)::(add l1 list2)
  |( (a,n)::l1 , (b,n2)::l2) when n > n2 -> (b,n2)::(add list1 l2)
  |( (a,n)::l1 , (b,n2)::l2) -> (*attention aux coefficients négatifs!*)
    match (a,b) with
      (a,b) when a = -b -> add l1 l2
    |_ -> (a+b,n)::(add l1 l2);;

add [(1,2);(2,6);(7,8);(2,12)] [(1,4);(3,6);(1,9)];;

(*ajoute les polynomes contenu dans list entre eux*)
let rec addList list = match list with
    [] | [[]] -> []
  |e::l -> add e (addList l);;

addList [ [(1,2);(2,4)];[(1,1);(2,3);(1,4)];[(2,2);(2,3)] ];;

(*soustrait le polynôme list1 au polynôme list2*)
let rec soustract list1 list2 = match (list1,list2) with
    ([],l)|(l,[]) -> l
  |( (a,n)::l1 , (b,n2)::l2) when n < n2 -> (a,n)::(soustract l1 list2)
  |( (a,n)::l1 , (b,n2)::l2) when n > n2 -> (-b,n2)::(soustract list1 l2)
  |( (a,n)::l1 , (b,n2)::l2) -> 
    match (a,b) with
      (a,b) when a = -b -> soustract l1 l2
    |_ -> (a-b,n)::(soustract l1 l2);;

soustract [(1,2);(2,6);(7,8);(2,12)] [(1,4);(3,6);(1,9)];;

(*multiplie le polynôme list1 avec le polynôme list2*)
let rec mult list1 list2 = match (list1,list2) with
    ([],_)|(_,[]) -> []
  |( (a,n)::l1 , (b,n2)::l2 ) -> add (add [(a*b,n+n2)] (mult [(a,n)] l2) ) (mult l1 list2) ;;

mult [(1,2);(2,3);(4,4)] [(1,1);(3,3);(2,5)];;

(*on rappel que la dérivée de aX^n est anX^(n-1) *)
(*derive le polynôme list*)
let rec deriv list = match list with
    []|[(_,0)] -> []
  |(a,n)::l -> (n*a,n-1)::(deriv l);;

deriv [(2,2);(2,3);(4,4)];;
